Skip to content

feat(plugin): Auto-wrap SQLiteDriver with SentrySQLiteDriver for Room users#1285

Open
0xadam-brown wants to merge 1 commit into
mainfrom
feat/wrap-sqlite-driver
Open

feat(plugin): Auto-wrap SQLiteDriver with SentrySQLiteDriver for Room users#1285
0xadam-brown wants to merge 1 commit into
mainfrom
feat/wrap-sqlite-driver

Conversation

@0xadam-brown

@0xadam-brown 0xadam-brown commented Jun 9, 2026

Copy link
Copy Markdown
Member

📜 Description

Adds a new bytecode method visitor that lets us auto-wrap all occurrences of SQLiteDriver with SentrySQLiteDriver whenever the driver is passed to a setDriver(SQLiteDriver) method.

For instance:

val database = Room.databaseBuilder(context, MyDatabase::class.java, "dbName")
     .setDriver(AndroidSQLiteDriver())
     .build()

becomes:

val database = Room.databaseBuilder(context, MyDatabase::class.java, "dbName")
     .setDriver(SentrySQLiteDriver.create(AndroidSQLiteDriver()))
     .build()

The wrapping policy is naive in that every SQLiteDriver passed to setDriver() is wrapped. That's deliberate because SentrySQLiteDriver protects against double-wrapping internally, which lets us keep our visitor implementation simple.

💡 Motivation and Context

Room 2.7 introduced RoomDatabase.Builder.setDriver(SQLiteDriver) as the new way to configure an underlying SQLite implementation (link), with the intention of eventually replacing SupportSQLiteOpenHelper. (Room 3.0+ does just that.)

The Sentry Android Gradle Plugin currently auto-instruments only the open helper path. Apps that adopt the driver-based API will lose automatic SQL performance instrumentation unless they manually wrap their driver with SentrySQLiteDriver.create(...) at every setDriver(...) call site.

This PR provides auto-wrapping for the driver path too.

Addresses GRADLE-107 / #1281

Preconditions

  1. sentry-android-sqlite version in the SAGP build must include SentrySQLiteDriver
  2. InstrumentationFeature.DATABASE must be enabled

Coverage

  • Auto-wraps SQLiteDriver for all Room users (sole Room access point is via its Room.DatabaseBuilder.setDriver() method).
  • SQLDelight users don't need driver auto-wrapping (they still use SupportSQLiteOpenHelper, which we already auto-wrap).
  • The few developers who use SQLiteDriver directly will need to wrap it manually.

💚 How did you test it?

[1] Added unit tests

[2] Performed benchmark tests against the DuckDuckGo app

tl;dr: Impact on build times looks acceptable. Auto-wrapping SQLiteDriver adds no meaningful cost on cold full builds, but roughly 1.5s- 2.5s (10–15%) compile-time overhead on warm incremental builds, as the instrumentable scans every non-Sentry class/method per compile.

Benchmark results: Click to expand

SQLiteDriver auto-wrap A/B benchmark results

Setup

Item Detail
App DuckDuckGo Android @ 1301996268
Plugin SAGP 6.10.0 from local benchmark/sqlite-driver-* branches
SDK 6.21.0 + compile stub for SentrySQLiteDriver
ON AndroidXSQLiteDriver always in the instrumentable chain
OFF AndroidXSQLiteDriver commented out
Everything else Identical (DATABASE feature, helper-wrap, Room DAO instrumentation)

Scenarios: cold clean build (5 iterations) and warm incremental build after ABI change to BookmarksDao.kt (7 iterations).

Note: SDK 6.21.0 + stub was used because DuckDuckGo's Kotlin 1.7 can't build with Sentry 8.43. This measures plugin instrumentation compile cost, not runtime span overhead.

Clean build (assembleInternalDebug + clean, cold daemon)

Metric With SQLiteDriver wrap Without Overhead
Mean 86.8s 87.5s -0.8% (~-0.7s)
Median 85.2s 87.4s -2.6%

No meaningful impact / within run-to-run noise.

Incremental build (warm daemon, DAO ABI tweak)

Metric With SQLiteDriver wrap Without Overhead
Mean 17.7s 16.0s +10.6% (~+1.7s)
Median 18.8s 16.4s +14.7% (~+2.4s)

This is the scenario that matters for day-to-day development: the driver instrumentable visits every non-Sentry class / method on each compile, even when only a Room DAO changes.

Takeaways

  1. Cold full builds: Overhead is negligible on a large app like DuckDuckGo.
  2. Incremental builds: ~ 10–15% compile-time cost when AndroidXSQLiteDriver is enabled, driven by broad class/method visitor activation (same pattern as Logcat).
  3. Caveats: SDK 6.21.0 + stub, not production 8.43+; measures plugin instrumentation cost only.

📝 Checklist

  • I reviewed the submitted code
  • I added tests to verify the changes
  • I updated the docs if needed
  • No breaking changes

🔮 Next steps

⚠️ Prior to merging this PR:

  • Update VERSION_SQLITE_DRIVER to match the sentry-android version that introduces SentrySQLiteDriver (PR here) + address other inline TODOs.
  • Update Android sample app to accept an SAGP enabled/disabled flag + manually verify auto-wrap functionality.

@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor
Messages
📖 Do not forget to update Sentry-docs with your feature once the pull request gets approved.

Generated by 🚫 dangerJS against 1548c9c

@0xadam-brown 0xadam-brown linked an issue Jun 9, 2026 that may be closed by this pull request
Comment thread CHANGELOG.md
### Features

- Auto-wrap SQLiteDriver with SentrySQLiteDriver for Room users ([#1281](https://github.com/getsentry/sentry-android-gradle-plugin/issues/1281))
- Gated on `sentry-android-sqlite` >= 8.44.0 and the existing `tracingInstrumentation` `DATABASE` feature

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: Update version number once we ship the SentrySQLiteDriver in sentry-android.

internal val VERSION_LOGCAT = SemVer(6, 17, 0)
internal val VERSION_APP_START = SemVer(7, 1, 0)
internal val VERSION_SQLITE = SemVer(6, 21, 0)
internal val VERSION_SQLITE_DRIVER = SemVer(8, 44, 0)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: Update version number once we ship the SentrySQLiteDriver in sentry-android.

@0xadam-brown 0xadam-brown force-pushed the feat/wrap-sqlite-driver branch 2 times, most recently from f64ad3f to 1c821b7 Compare June 10, 2026 14:41
}
}

@Ignore(SQLITE_DRIVER_IGNORE_REASON)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: Remove @Ignore once we ship the SentrySQLiteDriver in sentry-android.

)
}

@Ignore(SQLITE_DRIVER_IGNORE_REASON)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: Remove @Ignore once we ship the SentrySQLiteDriver in sentry-android.

assertInstrumentableChain(build, "AndroidXSQLiteOpenHelper", "AndroidXRoomDao")
}

@Ignore(SQLITE_DRIVER_IGNORE_REASON)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: Remove @Ignore once we ship the SentrySQLiteDriver in sentry-android.

)
}

@Ignore(SQLITE_DRIVER_IGNORE_REASON)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: Remove @Ignore once we ship the SentrySQLiteDriver in sentry-android.

… users (GRADLE-107)

Adds a new ASM bytecode method visitor that lets us auto-wrap all occurrences of SQLiteDriver with SentrySQLiteDriver whenever the driver is passed to Room.DatabaseBuilder.setDriver(...).

For instance:

val database = Room.databaseBuilder(context, MyDatabase::class.java, "dbName")
     .setDriver(AndroidSQLiteDriver())
     .build()

becomes:

val database = Room.databaseBuilder(context, MyDatabase::class.java, "dbName")
     .setDriver(SentrySQLiteDriver.create(AndroidSQLiteDriver()))
     .build()

The wrapping policy is naive in that every SQLiteDriver passed to setDriver() is wrapped. That's deliberate because SentrySQLiteDriver protects against double-wrapping internally, which lets us keep our visitor implementation simple.

Preconditions:

1. InstrumentationFeature.DATABASE is enabled
2. The owning app is using a version of sentry-android-sqlite that includes SentrySQLiteDriver

Coverage:

- Auto-wraps SQLiteDriver for all Room users (sole Room access point is via its Room.DatabaseBuilder.setDriver() method).
- SQLDelight users don't need driver auto-wrapping (they still use SupportSQLiteOpenHelper, which we already auto-wrap).
- The few developers who use SQLiteDriver directly will need to wrap it manually.
@0xadam-brown 0xadam-brown force-pushed the feat/wrap-sqlite-driver branch from 1c821b7 to 1548c9c Compare June 10, 2026 15:27
@0xadam-brown 0xadam-brown marked this pull request as ready for review June 10, 2026 15:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Auto-wrap SQLiteDriver with SentrySQLiteDriver for Room users

1 participant